#ifndef __VIRTUAL_MATCH_MEM_H__
#define __VIRTUAL_MATCH_MEM_H__

#include <memory.h>
#include <stdlib.h>

    struct ListNode
    {
        ListNode():next(0), data(0)
        {}
        ListNode* next;
        void* data;
    };

#define PL sizeof(ListNode *)

template<typename T, size_t INIT, size_t STEP>
class MemCache
{
public:
    MemCache()
    {
        unsigned int unit_len = sizeof(T)+PL;
        _mem_blocks_head = (ListNode *)malloc(unit_len*INIT + PL);
        _mem_blocks_head->next = 0;
        _mem_blocks_tail = _mem_blocks_head;

        unsigned char *p = (((unsigned char *)_mem_blocks_head) + PL);
        _available_list_head = (ListNode*)p;
        for(int i = 0; i < int(INIT)-1; ++i, p += unit_len)
        {
            ((ListNode*)p)->next = (ListNode*)(p + unit_len);
        }
        _available_list_tail = (ListNode*)p;
        _available_list_tail->next = 0;


    }

    ~MemCache()
    {
        for(ListNode*p = _mem_blocks_head; p != 0; )
		{
			ListNode* q = p->next;
            free(p);
			p=q;
		}
        _mem_blocks_head = 0;
        _mem_blocks_tail = 0;
        _available_list_head = 0;
        _available_list_tail = 0;
    }

    T* Alloc()
    {
        T* ret = 0;
        if(_available_list_head == 0)
        {
            unsigned int unit_len = sizeof(T)+PL;
            ListNode* new_mem_block = (ListNode *)malloc(unit_len*STEP + PL);
            _mem_blocks_tail->next = new_mem_block;
            _mem_blocks_tail = new_mem_block;
			_mem_blocks_tail->next = 0;
            
            unsigned char *p = (((unsigned char *)new_mem_block) + PL);
            _available_list_head = (ListNode*)p;
            for(int i = 0; i < int(INIT)-1; ++i, p += unit_len)
            {
                ((ListNode*)p)->next = (ListNode *)(p + unit_len);
            }
            _available_list_tail = (ListNode*)p;
            _available_list_tail->next = 0;
        }

        ret = (T *)(((unsigned char*)_available_list_head) + PL);
        _available_list_head = _available_list_head->next;
        if(_available_list_head == 0)
            _available_list_tail = 0;

        return ret;
    }
    void Free(T* p)
    {
       ListNode* node = (ListNode *)(((unsigned char*)p) - PL);
       node->next = 0;
       if(_available_list_tail == 0)
           _available_list_head = _available_list_tail = node;
       else
       {
           _available_list_tail->next = node;
           _available_list_tail = node;
       }
    }

protected:
    ListNode* _mem_blocks_head;//mem blocks allocated by malloc/new call..
    ListNode* _mem_blocks_tail;
    ListNode* _available_list_head; //available list, recycle the freed node space...
    ListNode* _available_list_tail;
};

#endif
